package com.aaa.marketresearch.webclient.web;

import com.aaa.marketresearch.dataresource.domain.*;
import com.aaa.marketresearch.dataresource.service.*;
import com.aaa.marketresearch.webclient.security.UserRoleEnum;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLDecoder;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * @author Nail
 */

@Controller
@RequestMapping(value = "/mobile")
public class MobileService {

    private static final Logger log = LoggerFactory.getLogger(MobileService.class);

    @Autowired
    private FamilyService familyService;

    @Autowired
    FamilyMemberService familyMemberService;

    @Autowired
    MarketService marketService;

    @Autowired
    GoodsService goodsService;

    @Autowired
    BillService billService;

    private static void initJSONHeader(final HttpServletResponse httpResponse) {
        httpResponse.setHeader("Connection", "close");
        httpResponse.setHeader("Content-Type", "application/json");
        httpResponse.setHeader("Expires", "Thu, 19 Nov 1981 08:52:00 GMT");
        httpResponse.setHeader("Cache-Control", "no-store, no-cache, must-revalidate, post-check=0, pre-check=0");
        httpResponse.setHeader("Pragma", "no-cache");
        httpResponse.setCharacterEncoding("UTF-8");
    }

    public static String readStream(final InputStream is, final int bufferSize) {
        final char[] buffer = new char[bufferSize];
        final StringBuilder out = new StringBuilder();
        try {
            final Reader in = new InputStreamReader(is, "UTF-8");
            try {
                for (; ; ) {
                    int rsz = in.read(buffer, 0, buffer.length);
                    if (rsz < 0)
                        break;
                    out.append(buffer, 0, rsz);
                }
            } finally {
                in.close();
            }
        } catch (UnsupportedEncodingException ex) {

        } catch (IOException ex) {

        }
        return out.toString();
    }

    @RequestMapping(value = "/login")
    void login(final HttpServletRequest httpRequest, final HttpServletResponse httpResponse) {
        String name = httpRequest.getParameter("name");
        String pass = httpRequest.getParameter("pass");

        try {
            StringBuilder builder = new StringBuilder();

            if (name == null || pass == null) {
                builder.append("{\"role\":\"");
                builder.append(UserRoleEnum.NONE.name());
                builder.append("\"}");
            } else {
                Family family = this.familyService.getByEmail(name);
                if (family != null && family.getPassword().equalsIgnoreCase(pass)) {
                    family.printJSON(builder);
                } else {
                    builder.append("{\"role\":\"");
                    builder.append(UserRoleEnum.NONE.name());
                    builder.append("\"}");
                }
            }


            String cntStr = builder.toString();
            byte[] outData = cntStr.getBytes(Charset.forName("UTF-8"));
            int len = outData.length;

            initJSONHeader(httpResponse);
            httpResponse.setContentLength(len);

            OutputStream out = httpResponse.getOutputStream();
            out.write(outData, 0, len);

            out.flush();
            out.close();

        } catch (IOException ex) {
            log.error("login {}", ex);
        }
    }

    @RequestMapping(value = "/getProfessions")
    void getProfessions(final HttpServletRequest httpRequest, final HttpServletResponse httpResponse) {
        try {

            final List<String> professions = familyMemberService.getProfessions(null);

            StringBuilder builder = new StringBuilder();

            builder.append("[");
            for (Iterator<String> itProfession = professions.iterator(); itProfession.hasNext(); ) {
                String profession = itProfession.next();
                builder.append("\"");
                builder.append(profession);
                builder.append("\"");
                if (itProfession.hasNext()) builder.append(",");
            }
            builder.append("]");

            String cntStr = builder.toString();
            byte[] outData = cntStr.getBytes(Charset.forName("UTF-8"));
            int len = outData.length;

            initJSONHeader(httpResponse);
            httpResponse.setContentLength(len);

            OutputStream out = httpResponse.getOutputStream();
            out.write(outData, 0, len);

            out.flush();
            out.close();

        } catch (IOException ex) {
            log.error("getProfessions {}", ex);
        }
    }

    @RequestMapping(value = "/getFamilyMembers")
    void getFamilyMembers(final HttpServletRequest httpRequest, final HttpServletResponse httpResponse) {

        String data = httpRequest.getParameter("familyId");
        Integer familyId = Integer.parseInt(data);

        StringBuilder builder = new StringBuilder();

        try {
            List<FamilyMember> familyMembers = familyMemberService.getAllForFamily(familyId);
            builder.append("[");
            for (Iterator<FamilyMember> itFamilyMember = familyMembers.iterator(); itFamilyMember.hasNext(); ) {
                FamilyMember familyMember = itFamilyMember.next();
                familyMember.printJSON(builder);
                if (itFamilyMember.hasNext()) builder.append(",");
            }
            builder.append("]");

            String cntStr = builder.toString();
            byte[] outData = cntStr.getBytes(Charset.forName("UTF-8"));
            int len = outData.length;

            initJSONHeader(httpResponse);
            httpResponse.setContentLength(len);

            OutputStream out = httpResponse.getOutputStream();
            out.write(outData, 0, len);

            out.flush();
            out.close();
        } catch (IOException ex) {
            log.error("getFamilyMembers {}", ex);
        }
    }

    @RequestMapping(value = "/saveFamilyMember")
    public void saveFamilyMembers(final HttpServletRequest httpRequest, final HttpServletResponse httpResponse) {
        try {
            String data = httpRequest.getParameter("data");
            if (data != null && data.length() > 0) {
                try {
                    JSONParser parser = new JSONParser();
                    JSONObject jObj = (JSONObject) parser.parse(data);

                    FamilyMember familyMember;
                    Object obj = jObj.get("id");
                    if (obj != null) {
                        int id = ((Long) obj).intValue();
                        familyMember = this.familyMemberService.getById(id);
                    } else {
                        familyMember = new FamilyMember();
                    }
                    familyMember.setWithJSONObject(jObj);
                    this.familyMemberService.save(familyMember);

                } catch (ParseException e) {
                    log.error("try to parse json" + e);
                }
            }

            String cntStr = "ok";
            byte[] outData = cntStr.getBytes(Charset.forName("UTF-8"));
            int len = outData.length;

            initJSONHeader(httpResponse);
            httpResponse.setContentLength(len);

            OutputStream out = httpResponse.getOutputStream();
            out.write(outData, 0, len);

            out.flush();
            out.close();
        } catch (IOException ex) {
            log.error("saveFamilyMembers {}", ex);
        }
    }

    @RequestMapping(value = "/getMarkets")
    void getMarkets(final HttpServletRequest httpRequest, final HttpServletResponse httpResponse) {
        try {
            StringBuilder builder = new StringBuilder();

            List<Market> markets = marketService.getAll();
            builder.append("[");
            for (Iterator<Market> itMarket = markets.iterator(); itMarket.hasNext(); ) {
                Market market = itMarket.next();
                market.printJSON(builder);
                if (itMarket.hasNext()) builder.append(",");
            }
            builder.append("]");

            String cntStr = builder.toString();
            byte[] outData = cntStr.getBytes(Charset.forName("UTF-8"));
            int len = outData.length;

            initJSONHeader(httpResponse);
            httpResponse.setContentLength(len);

            OutputStream out = httpResponse.getOutputStream();
            out.write(outData, 0, len);

            out.flush();
            out.close();

        } catch (IOException ex) {
            log.error("getMarkets {}", ex);
        }
    }

    @RequestMapping(value = "/saveMarket")
    public void saveMarket(final HttpServletRequest httpRequest, final HttpServletResponse httpResponse) {
        try {
            String data = httpRequest.getParameter("data");
            if (data != null && data.length() > 0) {
                try {
                    JSONParser parser = new JSONParser();
                    JSONObject jObj = (JSONObject) parser.parse(data);

                    Market market;
                    Object obj = jObj.get("id");
                    if (obj != null) {
                        int id = ((Long) obj).intValue();
                        market = this.marketService.getById(id);
                    } else {
                        market = new Market();
                    }
                    market.setWithJSONObject(jObj);
                    this.marketService.save(market);

                } catch (ParseException e) {
                    log.error("try to parse json" + e);
                }
            }

            String cntStr = "ok";
            byte[] outData = cntStr.getBytes(Charset.forName("UTF-8"));
            int len = outData.length;

            initJSONHeader(httpResponse);
            httpResponse.setContentLength(len);

            OutputStream out = httpResponse.getOutputStream();
            out.write(outData, 0, len);

            out.flush();
            out.close();
        } catch (IOException ex) {
            log.error("saveMarket {}", ex);
        }
    }

    @RequestMapping(value = "/getOffer")
    void getOffer(final HttpServletRequest httpRequest, final HttpServletResponse httpResponse) {
        String paramBarcode = httpRequest.getParameter("barcode");
        try {
            StringBuilder builder = new StringBuilder();

            Long barcode = Long.parseLong(paramBarcode);

            Goods goods = goodsService.getByBarcode(barcode);

            if (goods != null) {
                goods.printJSON(builder);
            } else {
                builder.append("{}");
            }

            String cntStr = builder.toString();
            byte[] outData = cntStr.getBytes(Charset.forName("UTF-8"));
            int len = outData.length;

            initJSONHeader(httpResponse);
            httpResponse.setContentLength(len);

            OutputStream out = httpResponse.getOutputStream();
            out.write(outData, 0, len);

            out.flush();
            out.close();
        } catch (IOException ex) {
            log.error("getOffer {}", ex);
        }
    }

    @RequestMapping(value = "/getOffers")
    void getOffers(final HttpServletRequest httpRequest, final HttpServletResponse httpResponse) {
        String partName = null;
        try {
            partName = readStream(httpRequest.getInputStream(), 16);
        } catch (IOException ex) {
            log.error("getOffers {}", ex);
        }

        try {

            List<Goods> goodsList;
            if (partName != null && partName.length() > 0) {
                String content = new String(partName.getBytes(), Charset.forName("UTF-8"));
                String decodedContent = URLDecoder.decode(content, "UTF-8");
                String[] splitContent = decodedContent.split("=");
                goodsList = goodsService.getWithPartNameLike(splitContent[1]);
            } else {
                goodsList = new ArrayList<Goods>();
            }

            StringBuilder builder = new StringBuilder();

            builder.append("[");
            for (Iterator<Goods> itGoods = goodsList.iterator(); itGoods.hasNext(); ) {
                Goods goods = itGoods.next();
                goods.printJSON(builder);
                if (itGoods.hasNext()) builder.append(",");
            }
            builder.append("]");

            String cntStr = builder.toString();
            byte[] outData = cntStr.getBytes(Charset.forName("UTF-8"));
            int len = outData.length;

            initJSONHeader(httpResponse);
            httpResponse.setContentLength(len);

            OutputStream out = httpResponse.getOutputStream();
            out.write(outData, 0, len);

            out.flush();
            out.close();
        } catch (IOException ex) {
            log.error("getOffers {}", ex);
        }
    }

    @RequestMapping(value = "/saveOffer")
    public void saveOffer(final HttpServletRequest httpRequest, final HttpServletResponse httpResponse) {
        try {
            String data = httpRequest.getParameter("data");
            if (data != null && data.length() > 0) {
                try {
                    JSONParser parser = new JSONParser();
                    JSONObject jObj = (JSONObject) parser.parse(data);

                    Goods goods;
                    Object obj = jObj.get("id");
                    if (obj != null) {
                        int id = ((Long) obj).intValue();
                        goods = this.goodsService.getById(id);
                    } else {
                        goods = new Goods();
                    }
                    goods.setWithJSONObject(jObj);
                    this.goodsService.save(goods);

                } catch (ParseException e) {
                    log.error("try to parse json" + e);
                }
            }

            String cntStr = "ok";
            byte[] outData = cntStr.getBytes(Charset.forName("UTF-8"));
            int len = outData.length;

            initJSONHeader(httpResponse);
            httpResponse.setContentLength(len);

            OutputStream out = httpResponse.getOutputStream();
            out.write(outData, 0, len);

            out.flush();
            out.close();
        } catch (IOException ex) {
            log.error("saveOffer {}", ex);
        }
    }

    @RequestMapping(value = "/saveBill")
    public void saveBill(final HttpServletRequest httpRequest, final HttpServletResponse httpResponse) {
        try {
            String data = null;
            try {
                data = readStream(httpRequest.getInputStream(), 32);
            } catch (IOException ex) {
                log.error("saveBill {}", ex);
            }

            if (data != null && data.length() > 0) {
                try {
                    JSONParser parser = new JSONParser();
                    JSONObject jBill = (JSONObject) parser.parse(data);

                    JSONArray content = (JSONArray) jBill.get("content");

                    int n = content.size();



                    if (n > 0) {

                        Bill bill = new Bill();

                        List<BillContent> billContentList = new ArrayList<>(n);

                        for (int i = 0; i < n; i++) {
                            JSONObject jObj = (JSONObject) content.get(i);

                            Market market = null;
                            Goods goods = null;
                            FamilyMember familyMember = null;
                            double capacity = 0.0;
                            double payedValue = 0.0;

                            Object obj;


                            obj = jObj.get("marketId");
                            if (obj != null) {
                                Integer marketId = ((Long) obj).intValue();
                                market = marketService.getById(marketId);
                            }

                            obj = jObj.get("offerId");
                            if (obj != null) {
                                Integer goodsId = ((Long) obj).intValue();
                                goods = goodsService.getById(goodsId);
                            }

                            obj = jObj.get("familyMemberId");
                            if (obj != null) {
                                Integer familyMemberId = ((Long) obj).intValue();
                                familyMember = familyMemberService.getById(familyMemberId);
                            }

                            obj = jObj.get("capacity");
                            if (obj != null) {
                                capacity = (Double) obj;
                            }

                            obj = jObj.get("payedValue");
                            if (obj != null) {
                                payedValue = (Double) obj;
                            }

                            if (market != null && goods != null && familyMember != null) {
                                BillContent billContent = new BillContent();
                                billContent.setBill(bill);
                                billContent.setFamilyMember(familyMember);
                                billContent.setMarket(market);
                                billContent.setGoods(goods);
                                billContent.setCapacity(capacity);
                                billContent.setPayedValue(payedValue);

                                billContentList.add(billContent);
                            }
                        }
                        bill.setContent(billContentList);

                        billService.save(bill);

                    }
                } catch (ParseException e) {
                    log.error("try to parse json" + e);
                }
            }

            String cntStr = "ok";
            byte[] outData = cntStr.getBytes(Charset.forName("UTF-8"));
            int len = outData.length;

            initJSONHeader(httpResponse);
            httpResponse.setContentLength(len);

            OutputStream out = httpResponse.getOutputStream();
            out.write(outData, 0, len);

            out.flush();
            out.close();
        } catch (IOException ex) {
            log.error("saveOffer {}", ex);
        }
    }

}
